/* Webman AI 绘画应用 */
import {translate, listenLink, hasChinese} from "/app/ai/js/util.js?v=3.9.4";
const {createApp, reactive} = Vue;
const {$, markdownit, addEventListener, location, setInterval, setTimeout, XMLHttpRequest,
    localStorage, alert, FormData, document} = window;
let app = {
    data() {
        return {
            uploadPercent: 0,
            defaultStyles: [
                {"photorealistic": "照片感", "pixar style": "皮克斯", "isometric clean": "微缩图", "pixel art": "像素化"},
                {"chibi": "Q版", "logo": "图标", "cyberpunk": "赛格朋克", "layered paper craft": "纸雕"}
            ],
            defaultVersions: {"7.0":"v7", "6.1":"v6", "5.2":"v5"},
            images: [],
            image: {
                model: "midjourney",
                version: "6.1",
                text: "",
                time: 0,
                ar: '1:1',
                widthRatio: '',
                heightRatio: '',
                chaos: 0,
                stylize: 100,
                styles: [],
                refs: [],
                iw: 1.8,
                others: '',
                fast: false,
                prompt: '',
                finalPrompt: '',
                imageUrl: '',
                errorMessage: '',
                buttons: []
            },
            imageToEdit: {},
            editor: {
                src: "",
                isDrawing: false,
                startX: 0,
                startY: 0,
                endX: 0,
                endY: 0,
                shapes: [],
                lassoPoints: [],
                selectedTool: "lasso"
            },
            settings: {
                allowAllFast: false
            },
            isMobile: false,
            leftBoxShow: true,
            showOptions: false,
            isDraggingOver: false,
        }
    },
    mounted() {
        this.initMarkdown();
        this.loadImages();
        this.checkStatus();
        setInterval(() => {
            this.checkStatus();
        }, 3000);
        this.scrollToBottom(true, false);
        this.checkMobile();
        setTimeout(() => {this.image.fast = this.isVip();}, 1000);
        addEventListener("resize", this.checkMobile);
        listenLink();
        this.loadSetting();
        this.loadVersion();
    },
    methods: {
        loadImages() {
            const data = localStorage.getItem("ai.mj.data");
            this.images = data ? JSON.parse(data).images : [];
            for (let image of this.images) {
                if (image.result) {
                    image.imageUrl = image.result;
                    delete image.result;
                }
            }
            this.images = this.images.filter((image) => image.type !== "text" && image.imageUrl !== "");
            for (let image of this.images) {
                if (image.progress === "100%") {
                    image.completed = true;
                } else {
                    this.checkCompleted(image);
                }
                if (image.zoom) {
                    image.zoom = "";
                }
            }
        },
        loadSetting(cb) {
            $.ajax({
                url: "/app/ai/task/settings",
                type: "GET",
                dataType: "json",
                success: (res) => {
                    this.settings = res.data;
                    if (cb) {
                        cb();
                    }
                }
            });
        },
        loadVersion() {
            const data = localStorage.getItem("ai.mj.settings");
            if (data) {
                const settings = JSON.parse(data);
                if (settings.version) {
                    this.image.version = settings.version;
                }
            }
        },
        saveVersion() {
            localStorage.setItem("ai.mj.settings", JSON.stringify({
                version: this.image.version
            }));
        },
        draw(image) {
            image = this.cloneImage(image);
            this.collectImage(image);
            this.scrollToBottom(true);
            this.leftBoxShow = false;
            translate({content: image.text, complete: (text, error) => {
                if (error) {
                    image.type = "text";
                    image.errorMessage = error;
                    return;
                }
                image.prompt = text;
                this.doDraw(image);
            }});
        },
        doDraw(image) {
            let headers = this.headers();
            headers["Content-Type"] = "application/json";
            $.ajax({
                url: "/app/ai/task/imagine",
                data: JSON.stringify({image}),
                type: "POST",
                dataType: "json",
                headers: headers,
                complete: () => {
                    this.saveData();
                },
                success: (res) => {
                    if (res.taskId) {
                        image.taskId = res.taskId;
                        return;
                    }
                    image.type = "text";
                    image.errorMessage = res.msg || (res.error && res.error.message) || "图像生成失败:" + JSON.stringify(res);
                }
            });
        },
        action(image, button) {
            if (button.custom_id.includes("::CustomZoom::")) {
                this.imageToEdit = this.cloneImage(image, true);
                this.imageToEdit.zoom = 2;
                this.imageToEdit.button = button;
                $('#zoomModal').modal('show');
                return;
            }
            if (button.custom_id.includes("::Inpaint::")) {
                this.imageToEdit = this.cloneImage(image, true);
                this.imageToEdit.button = button;
                this.editor.src = image.smallUrl || image.imageUrl;
                this.editorResetCanvas();
                $('#varyModal').modal('show');
                return;
            }
            let newImage = this.cloneImage(image);
            this.collectImage(newImage);
            newImage.prompt = image.prompt;
            this.doAction(image.taskId, newImage, button);
        },
        doAction(taskId, image, button, mask) {
            button.clicked = true;
            const customId = button.custom_id;
            image.type = "images";
            this.saveData();
            this.scrollToBottom(true);
            $.ajax({
                url: "/app/ai/task/action",
                data: {taskId, customId, image, mask},
                type: "POST",
                dataType: "json",
                headers: this.headers(),
                complete: () => {
                    this.saveData();
                },
                success: (res) => {
                    if (res.taskId) {
                        image.taskId = res.taskId;
                        if (customId.includes("::CancelJob::")) {
                            this.images = this.images.filter((img) => img.taskId !== taskId);
                        }
                        return;
                    }
                    image.type = "text";
                    image.errorMessage = res.error ? res.error.message : res.msg || "操作失败 " + JSON.stringify(res);
                }
            });
        },
        headers() {
            return {version: parent.ai.setting.version};
        },
        doZoom() {
            let image = this.cloneImage(this.imageToEdit);
            this.collectImage(image);
            this.scrollToBottom(true);
            translate({content: image.text, complete: (text, error) => {
                if (error) {
                    image.type = "text";
                    image.errorMessage = error;
                    return;
                }
                image.prompt = text;
                this.doAction(this.imageToEdit.taskId, image, this.imageToEdit.button);
            }});
            $('#zoomModal').modal('hide');
        },
        doVary() {
            let mask = this.editorCanvasToImage().substring(22);
            let image = this.cloneImage(this.imageToEdit);
            this.collectImage(image);
            this.scrollToBottom(true);
            translate({content: image.text, complete: (text, error) => {
                if (error) {
                    image.type = "text";
                    image.errorMessage = error;
                    return;
                }
                image.prompt = text;
                this.doAction(this.imageToEdit.taskId, image, this.imageToEdit.button, mask);
            }});
            $('#varyModal').modal('hide');
        },
        buttonInfo(button) {
            const map = {
                "U1": this.isMobile ? ["选1", "选择图1"] : ["选择1", "选择图1"],
                "U2": this.isMobile ? ["选2", "选择图1"] : ["选择2", "选择图2"],
                "U3": this.isMobile ? ["选3", "选择图1"] : ["选择3", "选择图3"],
                "U4": this.isMobile ? ["选4", "选择图1"] : ["选择4", "选择图4"],
                "V1": this.isMobile ? ["变1", "变换图1"] : ["变换1", "变换图1"],
                "V2": this.isMobile ? ["变2", "变换图1"] : ["变换2", "变换图2"],
                "V3": this.isMobile ? ["变3", "变换图1"] : ["变换3", "变换图3"],
                "V4": this.isMobile ? ["变4", "变换图1"] : ["变换4", "变换图4"],
                "🔄": ["🔄", "重新生成"],
                "Upscale (Subtle)": ["高清(微调)", "生成2倍高清图像并保持细节"],
                "Upscale (Creative)": ["高清(创意)", "生成2倍高清图像并添加创意"],
                "Upscale (2x)": ["高清(2倍)", "生成2倍高清图像"],
                "Upscale (4x)": ["高清(4倍)", "生成4倍高清图像"],
                "Vary (Subtle)": ["🪄变换(微调)", "变换图像并保持细节"],
                "Vary (Strong)": ["🪄变换(强烈)", "变换图像并添加创意"],
                "Vary (Region)": ["🖌️重绘(区域)", "重绘选定区域的图像"],
                "Zoom Out 2x": ["🔍扩图(2倍)", "向四周扩展图像"],
                "Zoom Out 1.5x": ["🔍扩图(1.5倍)", "向四周扩展图像"],
                "Custom Zoom": ["🔍扩图(自定义)", "自定义扩展图像"],
                "⬅️": ["⬅️", "向左扩图"],
                "➡️": ["➡️", "向右扩图"],
                "⬆️": ["⬆️", "向上扩图"],
                "⬇️": ["⬇️", "向下扩图"],
                "Make Square": ["🟦正方形", "将图像扩展为正方形"],
                "Redo Upscale (Subtle)": ["重做高清(微调)", "重新生成2倍高清图像并保持细节"],
                "Redo Upscale (Creative)": ["重做高清(创意)", "重新生成2倍高清图像并添加创意"],
                "Redo Upscale (2x)": ["重做高清(2倍)", "重新生成2倍高清图像"],
                "Redo Upscale (4x)": ["重做高清(4倍)", "重新生成4倍高清图像"],
            };
            let name = button.label || button.emoji && button.emoji.name;
            let info = map[name];
            return info ? {name: info[0], title: info[1]} : null
        },
        cloneImage(image, all) {
            let newImage = JSON.parse(JSON.stringify(image));
            if (!all) {
                newImage.type = "images";
                newImage.progress = newImage.loadedProgress = "0%";
                newImage.taskId = newImage.errorMessage = newImage.prompt = newImage.finalPrompt = newImage.imageUrl = newImage.smallUrl = newImage.downloadUrl = newImage.action = "";
                newImage.completed = false;
                newImage.buttons = [];
            }
            newImage.time = Date.now();
            newImage = reactive(newImage);
            return newImage;
        },
        getStyleNames(image) {
            let names = [];
            for (const style of image.styles || []) {
                for (const styleGroup of this.defaultStyles) {
                    for (const key in styleGroup) {
                        if (key === style) {
                            names.push(styleGroup[key]);
                        }
                    }
                }
            }
            return names;
        },
        checkStatus() {
            for (const image of this.images) {
                if (image.progress !== "100%" && image.taskId) {
                    $.ajax({
                        url: "/app/ai/task/status",
                        data: {model: image.model, taskId: image.taskId},
                        dataType: "json",
                        success: (res) => {
                            const data = res.data;
                            if (res.code) {
                                image.progress = "100%";
                                image.type = "text";
                                image.errorMessage = `[ ${res.msg} ] \n ${res.detail||''}`;
                                this.saveData();
                                return;
                            }
                            image.progress = data.progress || image.progress;
                            if (!image.imageUrl && data.imageUrl) {
                                this.scrollToBottom();
                            }
                            image.imageUrl = data.imageUrl;
                            image.smallUrl = data.smallUrl || "";
                            image.downloadUrl = data.downloadUrl || "";
                            image.urlBig = data.urlBig;
                            if (image.buttons !== data.buttons) {
                                image.buttons = data.buttons;
                                this.scrollToBottom();
                            }
                            if (image.finalPrompt !== data.finalPrompt) {
                                image.finalPrompt = data.finalPrompt;
                                this.scrollToBottom();
                            }
                            image.action = data.action;
                            if (data.failReason) {
                                image.progress = "100%";
                                image.type = "text";
                                image.errorMessage = data.failReason;
                            } else if (data.progress === "Stopped") {
                                image.progress = "100%"
                                image.type = "text";
                                image.errorMessage = "图像生成存在不合法的内容";
                            } else if (data.status === "FINISHED") {
                                image.progress = "100%";
                            }
                            this.saveData();
                        }
                    });
                }
            }
        },
        clearContent() {
            this.image.text = "";
            this.$refs["content"].focus();
        },
        toggleStyle(value) {
            if (this.image.styles.includes(value)) {
                this.image.styles.splice(this.image.styles.indexOf(value), 1);
            } else {
                this.image.styles.push(value);
            }
        },
        openUploadImage() {
            this.$refs["uploadInput"].click();
        },
        uploadImage(event) {
            const file = event.target.files[0];
            this.doUploadImage(file);
            this.$refs["uploadForm"].reset();
        },
        doUploadImage(file, cb) {
            const formData = new FormData();
            if (file.size > 10 * 1024 * 1024) {
                return alert("单个文件不能大于10M");
            }
            formData.append("image", file);
            $.ajax({
                url: "/app/ai/upload/image",
                type: "POST",
                data: formData,
                processData: false,
                contentType: false,
                xhr: () => {
                    const xhr = new XMLHttpRequest();
                    xhr.upload.addEventListener("progress", (event) => {
                        if (event.lengthComputable) {
                            this.uploadPercent = Math.round((event.loaded / event.total) * 100);
                        }
                    }, false);
                    return xhr;
                },
                success: (res) => {
                    if (cb) {
                        cb(res);
                    }
                    if (!res.code) {
                        if (this.image.refs.length < 6) {
                            this.image.refs.push(location.protocol + "//" + location.host + res.data.url);
                        }
                    }
                },
                complete: () => {
                    this.uploadPercent = 0;
                }
            });
        },
        scrollToBottom(force, smooth) {
            const messageBox = this.$refs["messageBox"];
            const behavior = smooth !== false ? "smooth" : "auto";
            if (force || messageBox.scrollHeight - messageBox.clientHeight <= messageBox.scrollTop + 100) {
                this.$nextTick(() => {
                    messageBox.scrollTo({top: messageBox.scrollHeight, behavior: behavior});
                });
            }
        },
        scrollToTop(smooth) {
            const behavior = smooth !== false ? "smooth" : "auto";
            this.$refs["messageBox"].scrollTo({top: 0, behavior: behavior});
        },
        collectImage(image) {
            this.images.push(image);
            this.checkCompleted(image);
            // 防止占用太多内存，只保留30条记录
            this.images = this.images.slice(-30);
        },
        saveData() {
            localStorage.setItem("ai.mj.data", JSON.stringify({
                images: this.images,
            }));
        },
        previewImage(imgUrl) {
            window.parent.ai.previewImage(imgUrl);
        },
        listenImageClick() {
            const that = this;
            $(document).on("click", ".message-list .message-body img", function () {
                let imgUrl = $(this).attr("src");
                const imgExt = imgUrl.split(".").pop();
                if (imgExt.length <= 4) {
                    imgUrl = imgUrl.replace("-sm.", ".");
                }
                that.previewImage(imgUrl);
            });
        },
        handleImageError(image) {
            image.errorTryCount = image.errorTryCount || 0;
            if (image.errorTryCount < 5) {
                image.errorTryCount++;
                if (image.smallUrl) {
                    let imageUrl = image.smallUrl;
                    image.smallUrl = image.imageRawUrl;
                    this.$nextTick(() => {
                        image.smallUrl = imageUrl;
                    });
                } else {
                    let imageUrl = image.imageUrl;
                    image.imageUrl = image.imageRawUrl;
                    this.$nextTick(() => {
                        image.imageUrl = imageUrl;
                    });
                }
            }
        },
        checkMobile() {
            this.isMobile = window.innerWidth <= 768;
        },
        initMarkdown() {
            this.md = markdownit().set({
                linkify: false,
                breaks: true,
                html: false,
                highlight: function (str, lang) {
                    const header = `<div class="d-flex justify-content-between align-items-center user-select-none" style="margin-top:-10px;margin-right:-8px;"><span class="text-secondary">${lang}</span><span class="block-copy ml-2 iconfont iconfont-bg"></span></div>`;
                    if (lang && hljs.getLanguage(lang)) {
                        return "<pre class=\"hljs\">" + header + "<code>" + hljs.highlight(str, {language: lang}).value + "</code></pre>";
                    }
                    return "<pre class=\"hljs\">" + header + "<code>" + hljs.highlightAuto(str).value + "</code></pre>";
                }
            });
        },
        markdown(content) {
            content = (typeof content === "string") || (typeof content === "number") ? content : JSON.stringify(content);
            return this.md.render(content || '');
        },
        listenLink() {
            const ai = this;
            $(document).on("click", ".message-list a", function (e) {
                const link = $(this);
                if (!ai.isMobile) {
                    if (link.attr("href").startsWith("/app/ai/user/vip")) {
                        ai.switchModule("vip");
                        e.preventDefault();
                        return false;
                    }
                    if (link.attr("href").startsWith("/app/ai/user")) {
                        ai.switchModule("me");
                        e.preventDefault();
                        return false;
                    }
                }
                link.attr("target", "_blank");
            });
        },
        clearImages() {
            this.images = [];
            this.saveData();
            this.showOptions = false;
        },
        onload(image, event) {
            if (event.target.naturalWidth && event.target.naturalHeight) {
                image.width = event.target.naturalWidth;
                image.height = event.target.naturalHeight;
            }
            if (parseInt(image.progress) > parseInt(image.loadedProgress)) {
                image.loadedProgress = image.progress;
                if (image.loadedProgress === "100%") {
                    setTimeout(()=>{image.completed = true;}, 2000);
                }
            }
        },
        checkCompleted(image) {
            if (image.type === "images" && image.progress === "0%") {
                const timer = setInterval(() => {
                    if (parseInt(image.progress) > 0) {
                        clearInterval(timer);
                    } else {
                        image.loadedProgress = Math.min( parseInt(image.loadedProgress) + 1, 90) + "%";
                    }
                }, image.fast ? 1000 : 3000);
            }
        },
        isVip() {
            return parent.ai.loginUser.vip;
        },
        tryToUseFastModel() {
            this.loadSetting(() => {
                if (!this.settings.allowAllFast) {
                    this.image.fast = false;
                    webman.error("只有VIP会员才能使用快速模式");
                    return;
                }
                this.image.fast = true;
            });
        },
        editorSetCanvas (event) {
            const img = event.target
            setTimeout(() => {
                this.$refs.canvas.width = img.width;
                this.$refs.canvas.height = img.height;
            }, 1000);
        },
        editorOnMouseDown(event) {
            const editor = this.editor;
            editor.isDrawing = true;
            const canvas = this.$refs.canvas;
            const rect = canvas.getBoundingClientRect();
            event = event.touches ? event.touches[0] : event;
            editor.startX = event.clientX - rect.left;
            editor.startY = event.clientY - rect.top;
            if (editor.selectedTool === "lasso") {
                editor.lassoPoints = [];
                editor.lassoPoints.push({ x: editor.startX, y: editor.startY });
            }
            this.editorDrawShapes();
        },
        editorOnMouseUp(event) {
            const editor = this.editor;
            if (editor.isDrawing) {
                editor.isDrawing = false;
                if (editor.selectedTool === "rectangle") {
                    editor.shapes.push({ type: "rectangle", x: editor.startX, y: editor.startY, width: editor.endX - editor.startX, height: editor.endY - editor.startY });
                } else if (editor.selectedTool === "lasso") {
                    editor.shapes.push({ type: "lasso", points: editor.lassoPoints });
                }
                this.editorDrawShapes();
                this.editorFillLastShape();
            }
        },
        editorOnMouseMove(event) {
            const editor = this.editor;
            if (editor.isDrawing) {
                const canvas = this.$refs.canvas;
                const rect = canvas.getBoundingClientRect();
                event = event.touches ? event.touches[0] : event;
                editor.endX = event.clientX - rect.left;
                editor.endY = event.clientY - rect.top;
                if (editor.selectedTool === "rectangle") {
                    this.editorDrawShapes();
                    this.editorDrawRectanglePreview();
                } else if (editor.selectedTool === "lasso") {
                    editor.lassoPoints.push({ x: editor.endX, y: editor.endY });
                    this.editorDrawShapes();
                    this.editorDrawLasso();
                }
            }
        },
        editorDrawShapes() {
            const editor = this.editor;
            const canvas = this.$refs.canvas;
            const ctx = canvas.getContext("2d");
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            editor.shapes.forEach(shape => {
                if (shape.type === "rectangle") {
                    ctx.beginPath();
                    ctx.rect(shape.x, shape.y, shape.width, shape.height);
                    ctx.fillStyle = "white";
                    ctx.fill();
                } else if (shape.type === "lasso") {
                    ctx.beginPath();
                    ctx.moveTo(shape.points[0].x, shape.points[0].y);
                    for (let i = 1; i < shape.points.length; i++) {
                        ctx.lineTo(shape.points[i].x, shape.points[i].y);
                    }
                    ctx.closePath();
                    ctx.fillStyle = "white";
                    ctx.fill();
                }
            });
        },
        editorDrawRectanglePreview() {
            const editor = this.editor;
            const canvas = this.$refs.canvas;
            const ctx = canvas.getContext("2d");
            ctx.beginPath();
            ctx.rect(editor.startX, editor.startY, editor.endX - editor.startX, editor.endY - editor.startY);
            ctx.stroke();
        },
        editorDrawLasso() {
            const editor = this.editor;
            const canvas = this.$refs.canvas;
            const ctx = canvas.getContext("2d");
            ctx.beginPath();
            ctx.moveTo(editor.lassoPoints[0].x, editor.lassoPoints[0].y);
            for (let i = 1; i < editor.lassoPoints.length; i++) {
                ctx.lineTo(editor.lassoPoints[i].x, editor.lassoPoints[i].y);
            }
            ctx.closePath();
            ctx.stroke();
        },
        editorFillLastShape() {
            const editor = this.editor;
            const canvas = this.$refs.canvas;
            const ctx = canvas.getContext("2d");
            const lastShape = editor.shapes[editor.shapes.length - 1];
            if (lastShape.type === "rectangle") {
                ctx.fillStyle = "white";
                ctx.fillRect(lastShape.x, lastShape.y, lastShape.width, lastShape.height);
            } else if (lastShape.type === "lasso") {
                ctx.fillStyle = "white";
                ctx.fill();
            }
        },
        editorSelectRectangleTool() {
            this.editor.selectedTool = "rectangle"; // 选择矩形选择工具
        },
        editorSelectLassoTool() {
            this.editor.selectedTool = "lasso"; // 选择套索工具
        },
        editorUndo() {
            const editor = this.editor;
            if (editor.shapes.length > 0) {
                editor.shapes.pop(); // 移除最后一个形状
                this.editorDrawShapes(); // 重新绘制所有形状
            }
        },
        editorResetCanvas() {
            this.editor.shapes = [];
            const canvas = this.$refs.canvas;
            const ctx = canvas.getContext("2d");
            ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空画布
        },
        editorCanvasToImage() {
            const newCanvas = document.createElement('canvas');
            const newContext = newCanvas.getContext('2d');
            newCanvas.width = this.$refs.canvas.width;
            newCanvas.height = this.$refs.canvas.height;
            newContext.fillStyle = 'black';
            newContext.fillRect(0, 0, newCanvas.width, newCanvas.height);
            newContext.drawImage(this.$refs.canvas, 0, 0);
            return newCanvas.toDataURL('image/png');
        },
        formatTime(timestamp) {
            if (!timestamp) {
                return "";
            }
            const date = new Date(timestamp);
            const now = new Date();
            const hours = date.getHours().toString().padStart(2, "0");
            const minutes = date.getMinutes().toString().padStart(2, "0");
            // 如果是当天的，返回 小时:分钟
            if (date.toDateString() === now.toDateString()) {
                return `今天${hours}:${minutes}`;
            }
            // 如果是昨天的，返回昨天
            const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
            if (date.toDateString() === yesterday.toDateString()) {
                return `昨天${hours}:${minutes}`;
            }
            // 如果是前天的，返回前天
            const beforeYesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 2);
            if (date.toDateString() === beforeYesterday.toDateString()) {
                return `前天${hours}:${minutes}`;
            }
            // 如果是今年的，返回 月-日 如 01-25
            if (date.getFullYear() === now.getFullYear()) {
                const month = (date.getMonth() + 1).toString().padStart(2, "0");
                const day = date.getDate().toString().padStart(2, "0");
                return `${month}-${day} ${hours}:${minutes}`;
            }
            // 其它返回 年-月-日 如 2021-03-16
            const year = date.getFullYear().toString();
            const month = (date.getMonth() + 1).toString().padStart(2, "0");
            const day = date.getDate().toString().padStart(2, "0");
            return `${year}-${month}-${day} ${hours}:${minutes}`;
        },
        hasChinese(content) {
            return hasChinese(content);
        },
        handleDrag(event) {
            event.dataTransfer.setData('text/plain', event.target.src);
        },
        handleDrop(event) {
            this.isDraggingOver = false;
            const files = event.dataTransfer.files;
            for (let i = 0; i < Math.min(files.length, 6); i++) {
                const file = files[i];
                if (file.type.startsWith("image")) {
                    this.doUploadImage(file);
                }
            }
            const src = event.dataTransfer.getData('text/plain');
            if (src && this.image.refs.length < 6) {
                this.image.refs.push(src);
            }
            event.preventDefault();
        },
        handlePaste(event) {
            const items = event.clipboardData.items;
            for (let i = 0; i < Math.min(items.length, 6); i++) {
                const item = items[i];
                if (item.type.indexOf("image") !== -1) {
                    const file = item.getAsFile();
                    this.doUploadImage(file);
                }
            }
        },
        handleDragEnter(event) {
            this.isDraggingOver = true;
        },
        handleDragLeave(event) {
            if (!event.relatedTarget) {
                this.isDraggingOver = false;
            }
        },
        importImage(image) {
            this.image.refs = [];
            this.image = Object.assign(this.image, image);
            this.scrollToBottom(true);
        },
        adjustTextareaHeight() {
            this.$refs.content.style.height = 'auto';
            this.$refs.content.style.height = Math.min(this.$refs.content.scrollHeight, this.isMobile ? 89 : 79) + 'px';
        },
        imageSize(image) {
            let widthRatio = image.width;
            let heightRatio = image.height;
            if (!widthRatio || !heightRatio) {
                widthRatio = image.widthRatio;
                heightRatio = image.heightRatio;
                if (image.ar !== 'customized') {
                    const ar = image.ar.split(':');
                    widthRatio = parseInt(ar[0]);
                    heightRatio = parseInt(ar[1]);
                }
            }
            let width = 360;
            let height = 360;
            if (widthRatio > heightRatio) {
                height = width * heightRatio / widthRatio;
            } else {
                width = height * widthRatio / heightRatio;
            }
            return {width, height};
        }
    }
}
window.painting = createApp(app).mount('#app');